﻿using Playnite.SDK;
using Playnite.SDK.Models;
using Playnite.SDK.Plugins;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CloneMetadata
{
    public class CloneMetadataProvider : OnDemandMetadataProvider
    {
        private readonly MetadataRequestOptions options;
        private readonly CloneMetadata plugin;
        private string basePath;
        private Game target;
        //private string basePath = @"C:\Users\JimmyMo\AppData\Roaming\Playnite\library\files\";

        public override List<MetadataField> AvailableFields => throw new NotImplementedException();

        public CloneMetadataProvider(MetadataRequestOptions options, CloneMetadata plugin)
        {
            this.options = options;
            this.plugin = plugin;
            this.basePath = Path.Combine(plugin.PlayniteApi.ApplicationSettings.DatabasePath, "files");
            if (this.basePath.Contains("%AppData%", StringComparison.OrdinalIgnoreCase))
            {
                this.basePath = this.basePath?.Replace("%AppData%", Environment.ExpandEnvironmentVariables("%AppData%"), StringComparison.OrdinalIgnoreCase);
            }
            this.target = this.GetGame(options.GameData.Name);
            //this.basePath = plugin.PlayniteApi.ApplicationSettings.DatabasePath;
        }

        private Game GetGame(string name)
        {
            //var games = this.plugin.PlayniteApi.Database.Games.Where(a => a.Name.Trim().ToLowerInvariant() == this.options.GameData.Name.Trim().ToLowerInvariant()).ToList();
            //var games = this.plugin.PlayniteApi.Database.Games.Where(a => this.options.GameData.Name.Trim().ToLowerInvariant().Contains(a.Name.Trim().ToLowerInvariant())).ToList();
            var games = this.plugin.PlayniteApi.Database.Games.Where(a => a.Name.Trim().ToLowerInvariant().Contains(this.options.GameData.Name.Trim().ToLowerInvariant())).ToList();
            if (games == null || games.Count <= 0)
            {
                this.plugin.PlayniteApi.Dialogs.ShowErrorMessage($"{name}", "Game Not Found");
                return null;
            }
            else if (games.Count > 1 && games.Count <= 5)
            {
                var msg = string.Join(", ", games);
                this.plugin.PlayniteApi.Dialogs.ShowMessage($"{msg}", "Ambiguous Games Found");
                var selectedGame = games[this.plugin.selectedIndex % games.Count];
                this.plugin.selectedIndex++;
                return selectedGame;
            }
            else if (games.Count > 5)
            {
                var msg = string.Join(", ", games);
                this.plugin.PlayniteApi.Dialogs.ShowErrorMessage($"too many ambiguous games found {games.Count}", "Ambiguous Games Found");
                return null;
            }
            return games[0];
        }

        public override string GetName(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Description == null)
            {
                return base.GetName(args);
            }
            else
            {
                return game.Name;
            }
        }
        // Override additional methods based on supported metadata fields.
        public override string GetDescription(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Description == null)
            {
                return base.GetDescription(args);
            }
            else
            {
                return game.Description;
            }
        }

        public override IEnumerable<MetadataProperty> GetAgeRatings(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.AgeRatings == null)
            {
                return base.GetAgeRatings(args);
            }
            else
            {
                return game.AgeRatings.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override MetadataFile GetBackgroundImage(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || string.IsNullOrEmpty(game.BackgroundImage))
            {
                return base.GetBackgroundImage(args);
            }
            else
            {
                return new MetadataFile(Path.Combine(this.basePath, game.BackgroundImage));
            }
        }

        public override int? GetCommunityScore(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.CommunityScore == null)
            {
                return base.GetCommunityScore(args);
            }
            else
            {
                return game.CommunityScore;
            }
        }

        public override MetadataFile GetCoverImage(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || string.IsNullOrEmpty(game.CoverImage))
            {
                return base.GetCoverImage(args);
            }
            else
            {
                return new MetadataFile(Path.Combine(this.basePath, game.CoverImage));
            }
        }

        public override int? GetCriticScore(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.CriticScore == null)
            {
                return base.GetCriticScore(args);
            }
            else
            {
                return game.CriticScore;
            }
        }

        public override IEnumerable<MetadataProperty> GetDevelopers(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Developers == null)
            {
                return base.GetDevelopers(args);
            }
            else
            {
                return game.Developers.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override IEnumerable<MetadataProperty> GetFeatures(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Features == null)
            {
                return base.GetFeatures(args);
            }
            else
            {
                return game.Features.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override IEnumerable<MetadataProperty> GetGenres(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Genres == null)
            {
                return base.GetGenres(args);
            }
            else
            {
                return game.Genres.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override MetadataFile GetIcon(GetMetadataFieldArgs args)
        {
            
            var game = this.target;
            if (game == null || string.IsNullOrEmpty(game.Icon))
            {
                return base.GetIcon(args);
            }
            else
            {
                //var temp = game.Icon.Split('\\');
                //string id = temp[0];
                //string fileName = temp[1];
                //FileSystem.PrepareSaveFile(Path.Combine(basePath, options.GameData.Id.ToString(), fileName));
                //File.Copy(Path.Combine(basePath, game.Icon), Path.Combine(basePath, options.GameData.Id.ToString(), fileName));
                return new MetadataFile(Path.Combine(this.basePath, game.Icon)); // @"C:\Users\JimmyMo\AppData\Roaming\Playnite\library\files\245eab82-062e-4ad2-a4fa-c835cfb436fc\1176aaf8-3fa9-4296-b543-fed92ededa5e.ico");
            }
        }

        public override IEnumerable<Link> GetLinks(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Links == null)
            {
                return base.GetLinks(args);
            }
            else
            {
                return game.Links;
            }
        }

        public override IEnumerable<MetadataProperty> GetPlatforms(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Platforms == null)
            {
                return base.GetPlatforms(args);
            }
            else
            {
                return game.Platforms.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override IEnumerable<MetadataProperty> GetPublishers(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Publishers == null)
            {
                return base.GetPublishers(args);
            }
            else
            {
                return game.Publishers.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override IEnumerable<MetadataProperty> GetRegions(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Regions == null)
            {
                return base.GetRegions(args);
            }
            else
            {
                return game.Regions.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override ReleaseDate? GetReleaseDate(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.ReleaseDate == null)
            {
                return base.GetReleaseDate(args);
            }
            else
            {
                return game.ReleaseDate;
            }
        }

        public override IEnumerable<MetadataProperty> GetSeries(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Series == null)
            { 
                return base.GetSeries(args);
            }
            else
            {
                return game.Series.Select(item => new MetadataNameProperty(item.Name));
            }
        }

        public override IEnumerable<MetadataProperty> GetTags(GetMetadataFieldArgs args)
        {
            var game = this.target;
            if (game == null || game.Tags == null)
            {
                return base.GetTags(args);
            }
            else
            {
                return game.Tags.Select(item => new MetadataNameProperty(item.Name));
            }
        }
    }
}